package frame;

import java.awt.Color;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDesktopPane;
import javax.swing.JLabel;

import robot.MouseRobot;
import br.com.wagnerpaz.javahook.HookManager;
import br.com.wagnerpaz.javahook.NativeKeyboardEvent;
import br.com.wagnerpaz.javahook.NativeKeyboardListener;
import br.com.wagnerpaz.javahook.NativeMouseEvent;
import br.com.wagnerpaz.javahook.NativeMouseListener;
import br.com.wagnerpaz.javahook.NativeMouseWheelEvent;

public class MainDesktop extends JDesktopPane {

	private static final long serialVersionUID = 1L;

	private JLabel potLabel = new JLabel();

	private JLabel ballLabel = new JLabel();

	private JLabel calcLabel = new JLabel();

	private JLabel referLabel = new JLabel();

	private JCheckBox checkBox = new JCheckBox();

	private JButton detectButton = new JButton();

	private MouseRobot robot = new MouseRobot();

	private Point currPixel = new Point();

	private int status = SET_POT_STATUS;

	public MainDesktop() {
		initLabels();
		initListeners();
	}

	private void initLabels() {
		JLabel potTitle = new JLabel();
		potTitle.setBounds(10, 10, 30, 20);
		potTitle.setText("袋口:");
		potLabel.setBounds(50, 10, 100, 20);
		potLabel.setForeground(Color.gray);
		add(potTitle);
		add(potLabel);

		JLabel ballTitle = new JLabel();
		ballTitle.setBounds(10, 40, 30, 20);
		ballTitle.setText("被击:");
		ballLabel.setBounds(50, 40, 100, 20);
		ballLabel.setForeground(Color.gray);
		add(ballTitle);
		add(ballLabel);

		JLabel calcTitle = new JLabel();
		calcTitle.setBounds(10, 70, 30, 20);
		calcTitle.setText("打点:");
		calcLabel.setBounds(50, 70, 100, 20);
		calcLabel.setForeground(Color.BLUE);
		add(calcTitle);
		add(calcLabel);

		checkBox.setText("自动瞄准");
		checkBox.setEnabled(false);
		checkBox.setBounds(130, 10, 100, 20);
		checkBox.setBackground(Color.WHITE);
		add(checkBox);

		referLabel.setBounds(140, 40, 100, 20);
		referLabel.setForeground(Color.red);
		add(referLabel);

		detectButton.setBounds(135, 70, 70, 20);
		detectButton.setText("定位");
		add(detectButton);
	}

	private void initListeners() {
		HookManager.installKeyboardHook(new NativeKeyboardListener() {
			public boolean keyPressed(NativeKeyboardEvent arg0) {
				int keyCode = arg0.getKeyCode();
				switch (keyCode) {
				case KeyEvent.VK_UP:
					robot.mouseMove(currPixel.x, currPixel.y - 1);
					return false;
				case KeyEvent.VK_DOWN:
					robot.mouseMove(currPixel.x, currPixel.y + 1);
					return false;
				case KeyEvent.VK_LEFT:
					robot.mouseMove(currPixel.x - 1, currPixel.y);
					return false;
				case KeyEvent.VK_RIGHT:
					robot.mouseMove(currPixel.x + 1, currPixel.y);
					return false;
				case KeyEvent.VK_TAB:
					switch (status) {
					case SET_POT_STATUS:
						status = SET_BALL_STATUS;
						break;
					case SET_BALL_STATUS:
						status = FINISH_STATUS;
						if (checkBox.isSelected()) {
							Point ballPixel = robot.detectBallPoint(currPixel);

							robot.setBallPoint(ballPixel);
							updatePointInfo(ballLabel, ballPixel);
						}

						updatePointInfo(calcLabel, robot.getCalcPoint());
						break;
					case FINISH_STATUS:
						resetStatus();
						robot.mouseMove(currPixel.x, currPixel.y);
						break;
					default:
						break;
					}

					return false;
				case KeyEvent.VK_0:
					if (!checkBox.isSelected()) {
						updatePointInfo(referLabel, currPixel);

						checkBox.setSelected(true);
						checkBox.setEnabled(true);

						robot.setReferPoint(currPixel);
						return false;
					} else {
						return true;
					}
				case KeyEvent.VK_Q:
				case KeyEvent.VK_W:
				case KeyEvent.VK_E:
				case KeyEvent.VK_A:
				case KeyEvent.VK_S:
				case KeyEvent.VK_D:
					if (checkBox.isSelected() && status != FINISH_STATUS) {
						status = FINISH_STATUS;
						Point ballPixel = robot.detectBallPoint(currPixel);
						Point potPixel = robot.getStandardPotPoint(keyCode);

						robot.setBallPoint(ballPixel);
						robot.setPotPoint(potPixel);

						updatePointInfo(ballLabel, ballPixel);
						updatePointInfo(potLabel, potPixel);
						updatePointInfo(calcLabel, robot.getCalcPoint());

						return false;
					} else {
						return true;
					}
				default:
					return true;
				}
			}

			public boolean keyReleased(NativeKeyboardEvent arg0) {
				return true;
			}

		});

		HookManager.installMouseHook(new NativeMouseListener() {
			public boolean mouseMoved(NativeMouseEvent arg0) {
				currPixel.setLocation(arg0.getX(), arg0.getY());

				switch (status) {
				case SET_POT_STATUS:
					robot.setPotPoint(currPixel);
					updatePointInfo(potLabel, currPixel);
					break;
				case SET_BALL_STATUS:
					robot.setBallPoint(currPixel);
					updatePointInfo(ballLabel, currPixel);
					break;
				default:
					break;
				}

				return true;
			}

			public boolean mousePressed(NativeMouseEvent arg0) {
				return true;
			}

			public boolean mouseReleased(NativeMouseEvent arg0) {
				return true;
			}

			public boolean mouseWheelMoved(NativeMouseWheelEvent arg0) {
				return true;
			}

		});

		detectButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				Point autoRefer = robot.detectReferPoint();

				if (autoRefer == null) {
					checkBox.setSelected(false);
				} else {
					updatePointInfo(referLabel, autoRefer);

					checkBox.setSelected(true);
					checkBox.setEnabled(true);

					robot.setReferPoint(autoRefer);
				}

				resetStatus();
			}
		});
	}

	private void updatePointInfo(JLabel label, Point p) {
		label.setText(p.x + ", " + p.y);
	}

	public void resetStatus() {
		status = SET_POT_STATUS;

		potLabel.setText("");
		ballLabel.setText("");
		calcLabel.setText("");
	}

	public int getStatus() {
		return status;
	}

	public static final int SET_POT_STATUS = 0;

	public static final int SET_BALL_STATUS = 1;

	public static final int FINISH_STATUS = 2;

}
